package mws;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class ReadWriteLockTest {

    public static void main(String[] args) throws InterruptedException {
        testRaceCondition();
        testConcurrentReads();
        testWriteReentrancy();
    }

    // 测试1：竞态条件
    static void testRaceCondition() throws InterruptedException {
        System.out.println("=== 测试1：竞态条件 ===");
        ReadWriteLock rwLock = new ReadWriteLock();
        AtomicInteger counter = new AtomicInteger(0);

        CountDownLatch latch = new CountDownLatch(2);

        // 线程1：先获取读锁，然后等待
        Thread t1 = new Thread(() -> {
            rwLock.getReadLock().lock();
            try {
                // 模拟读取操作
                Thread.sleep(100);
                counter.incrementAndGet();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                rwLock.getReadLock().unlock();
                latch.countDown();
            }
        });

        // 线程2：尝试获取写锁
        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(10); // 确保t1先获取读锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            rwLock.getWriteLock().lock();
            counter.incrementAndGet();
            rwLock.getWriteLock().unlock();
            latch.countDown();
        });

        t1.start();
        t2.start();
        latch.await();

        System.out.println("最终计数: " + counter.get());
        // 预期：2，但如果存在竞态条件可能不是2
    }

    // 测试2：并发读取
    static void testConcurrentReads() throws InterruptedException {
        System.out.println("\n=== 测试2：并发读取 ===");
        ReadWriteLock rwLock = new ReadWriteLock();
        int threadCount = 5;
        CountDownLatch latch = new CountDownLatch(threadCount);
        AtomicInteger successCount = new AtomicInteger(0);

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                rwLock.getReadLock().lock();
                successCount.incrementAndGet();
                // 读锁应该可以并发获取
                rwLock.getReadLock().unlock();
                latch.countDown();
            }).start();
        }

        latch.await();
        System.out.println("成功获取读锁的线程数: " + successCount.get());
        // 应该是5，但可能出现数据竞争导致计数错误
    }

    // 测试3：写锁重入
    static void testWriteReentrancy() {
        System.out.println("\n=== 测试3：写锁重入 ===");
        ReadWriteLock rwLock = new ReadWriteLock();

        // 同一个线程多次获取写锁
        rwLock.getWriteLock().lock();
        System.out.println("第一次获取写锁成功");

        rwLock.getWriteLock().lock(); // 重入
        System.out.println("第二次获取写锁成功");

        rwLock.getWriteLock().unlock();
        System.out.println("第一次释放写锁");

        rwLock.getWriteLock().unlock();
        System.out.println("第二次释放写锁");

        // 预期：应该能正常重入和释放
    }
}
 class ReadWriteLockTestV2       {
    public static void main(String[] args) throws InterruptedException {
        SimpleReadWriteLock rwLock = new SimpleReadWriteLock();

        // 测试基本功能
        System.out.println("=== 基本功能测试 ===");

        // 读锁测试
        Thread reader1 = new Thread(() -> {
            rwLock.getReadLock().lock();
            System.out.println("读线程1获取锁");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            rwLock.getReadLock().unlock();
            System.out.println("读线程1释放锁");
        });

        Thread reader2 = new Thread(() -> {
            rwLock.getReadLock().lock();
            System.out.println("读线程2获取锁");
            try { Thread.sleep(500); } catch (InterruptedException e) {}
            rwLock.getReadLock().unlock();
            System.out.println("读线程2释放锁");
        });

        // 写锁测试
        Thread writer = new Thread(() -> {
            rwLock.getWriteLock().lock();
            System.out.println("写线程获取锁");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            rwLock.getWriteLock().unlock();
            System.out.println("写线程释放锁");
        });

        reader1.start();
        reader2.start();
        Thread.sleep(100); // 让读锁先获取
        writer.start();

        reader1.join();
        reader2.join();
        writer.join();
    }
}